package com.ctl.utils.encryp.md5;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class MD5Utils {

    private String inStr;
    private MessageDigest md5;

    /**
     * Constructs the MD5 object and sets the string whose MD5 is to be
     * computed.
     *
     * @param inStr the <code>String</code> whose MD5 is to be computed
     */
    public MD5Utils(String inStr) {
        this.inStr = inStr;
        try {
            this.md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }

    /**
     * Computes the MD5 fingerprint of a string.
     *
     * @return the MD5 digest of the input <code>String</code>
     */
    public String compute() {
        // convert input String to a char[]
        // convert that char[] to byte[]
        // get the md5 digest as byte[]
        // bit-wise AND that byte[] with 0xff
        // prepend "0" to the output StringBuffer to make sure that we don't end
        // up with
        // something like "e21ff" instead of "e201ff"

        char[] charArray = this.inStr.toCharArray();

        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];

        byte[] md5Bytes = this.md5.digest(byteArray);

        StringBuffer hexValue = new StringBuffer();

        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16)
                hexValue.append("0");
            hexValue.append(Integer.toHexString(val));
        }

        return hexValue.toString();
    }

    public static List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        List<Integer> current = new ArrayList<>();
        backtrack(nums, used, current, result);
        return result;
    }

    private static void backtrack(int[] nums, boolean[] used, List<Integer> current, List<List<Integer>> result) {
        if (current.size() == nums.length) {
            result.add(new ArrayList<>(current));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            if (used[i]) {
                continue;
            }

            // 做选择
            current.add(nums[i]);
            used[i] = true;

            // 进入下一层决策树
            backtrack(nums, used, current, result);

            // 撤销选择
            current.remove(current.size() - 1);
            used[i] = false;
        }
    }

    public static String sha256Hex(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes("UTF-8"));
            return bytesToHex(hash);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }


    private static final String SECRET_KEY = "nzgi2g9gi7odbvxw"; // 必须为 16, 24 或 32 字节




    public static void main(String[] args) {

        String password = "han@chao12";
        String hashedPassword = sha256Hex(password);
        System.out.println(hashedPassword);

//        String[] str = {"han@chao12", "659699", "nzgi2g9gi7odbvxw"};
        String[] str = {"aGFuQGNoYW8xMg==", "659699", "nzgi2g9gi7odbvxw"};
        int[] nums = {0, 1, 2};
        List<List<Integer>> permutations = permute(nums);

        int[] nums3 = {0};
        permutations.addAll(permute(nums3));
        int[] nums4 = {0, 1};
        permutations.addAll(permute(nums4));
        int[] nums5 = {0, 2};
        permutations.addAll(permute(nums5));

        String[] tszf=new String[]{"","!","@","#","$","%","^","&","*","+"};
        // 打印所有排列nums2
        for (List<Integer> permutation : permutations) {
            for (int i = 0; i < tszf.length ;i++) {
                StringJoiner stringJoiner = new StringJoiner(tszf[i]);
                permutation.forEach(index -> {
                    stringJoiner.add(str[index]);
                });
                System.out.println(stringJoiner);
                MD5Utils md5 = new MD5Utils(stringJoiner.toString());
                String postString = md5.compute();
                System.out.println("加密后的字符:" + postString);
                if (postString.equals("0636e7832596d4a084efef07bb5fb5d3")) {
                    System.out.println(true);
                } else {
                    md5 = new MD5Utils(postString);
                    postString = md5.compute();
                    System.out.println("加密后的字符:" + postString);
                    if (postString.equals("0636e7832596d4a084efef07bb5fb5d3")) {
                        System.out.println(true);
                    }
                }
            }

        }


    }
}
